package com.hyfrogx.modules.app.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hyfrogx.common.exception.MyException;
import com.hyfrogx.common.exception.ServiceException;
import com.hyfrogx.common.log.LogEnum;
import com.hyfrogx.common.log.LogUtils;
import com.hyfrogx.common.utils.MD5Utils;
import com.hyfrogx.common.utils.QueryExt;
import com.hyfrogx.common.utils.R;
import com.hyfrogx.common.utils.RedisUtils;
import com.hyfrogx.modules.app.dao.UserDao;
import com.hyfrogx.modules.app.entity.HyInviteInfo;
import com.hyfrogx.modules.app.entity.HyScore;
import com.hyfrogx.modules.app.entity.Sms;
import com.hyfrogx.modules.app.entity.User;
import com.hyfrogx.modules.app.form.ClientUserForm;
import com.hyfrogx.modules.app.service.HyInviteInfoService;
import com.hyfrogx.modules.app.service.HyScoreService;
import com.hyfrogx.modules.app.service.SmsService;
import com.hyfrogx.modules.app.service.UserService;
import com.hyfrogx.modules.app.utils.FrogConstant;
import com.hyfrogx.modules.app.utils.FrogxTaskCode;
import com.hyfrogx.modules.manage.entity.HyProductionScaleEntity;
import com.hyfrogx.modules.manage.entity.task.TaskRewardEntity;
import com.hyfrogx.modules.manage.entity.task.TaskUserInfoEntity;
import com.hyfrogx.modules.manage.service.HyProductionVacuateService;
import com.hyfrogx.modules.manage.service.task.TaskRewardService;
import com.hyfrogx.modules.manage.service.task.TaskUserInfoService;
import com.hyfrogx.modules.user.entity.HyUserBean;
import com.hyfrogx.modules.user.service.HyUserBeanService;
import io.swagger.annotations.ApiModelProperty;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.hyfrogx.modules.app.utils.Thumbnailator;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

/**
 * @author ：Li9527
 * @date ：Created in 2019-09-16 12:58
 * @description：${description}
 * @modified By：
 * @version: 1.0.0
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SmsService smsService;

    @Autowired
    private HyUserBeanService hyUserBeanService;
    @Autowired
    private HyScoreService hyScoreService;
    @Autowired
    private TaskRewardService rewardService;
    @Autowired
    private TaskUserInfoService userInfoService;
    @Autowired
    private HyInviteInfoService inviteInfoService;
    @Autowired
    private HyProductionVacuateService vacuateService;

    private Map<Object, Object> scoreManager;

    Logger SMS_LOG = LogUtils.Logger(LogEnum.SMS_LOGS);

    @PostConstruct
    private Map<Object, Object> getCacheManage() {
        if (null == scoreManager) {
            scoreManager = redisUtils.getMap(FrogConstant.RedisKey.ACCOUNT);
        }
        return scoreManager;
    }

    @Override
    public R sendSmsCode(String mobile) {
        // 先去redis 查询是否 60S内已经发送
        Object tempCode = redisUtils.get(FrogConstant.DEFAULT_CODE_KEY + mobile);
        if (tempCode != null) {
            return R.ok("验证码未失效，请失效后再次申请");
        }

        // 获取4位验证码
        String code = RandomUtil.randomNumbers(4);

        // 保存进redis 过期时间60秒
        redisUtils.set(FrogConstant.DEFAULT_CODE_KEY + mobile, code, FrogConstant.SMS_CODE_EXPIRE);

        // 发送短信 测试可用先注释,通过redis查看
        ArrayList<String> params = new ArrayList<>();
        params.add(code);
        SMS_LOG.info("手机号：" + mobile + ";短信模板：" + FrogConstant.SMS_TMP_YZM + ";验证码：" + code);
        boolean issuccess = smsService.sendSms(mobile, FrogConstant.SMS_TMP_YZM, params);
        // 发送失败删除redis
        redisUtils.delete(FrogConstant.DEFAULT_CODE_KEY + mobile);

        return R.error("验证码发送失败!");
    }

    @Override
    public R sendSmsByMeetInvite(String mobile, String zoomTab) {
        // 发送短信 测试可用先注释,通过redis查看
        ArrayList<String> params = new ArrayList<>();
        SMS_LOG.info("手机号：" + mobile + ";短信模板：" + FrogConstant.SMS_JOIN_MEET);
        params.add(zoomTab);
        boolean success = smsService.sendSms(mobile, FrogConstant.SMS_JOIN_MEET, params);
        if (success) {
            // 持久化
            Sms o = new Sms();
            o.setPhone(mobile);
            o.setStatus(1);
            o.setDate(new Date());
            o.setContent("手机号：" + mobile + ";短信模板：" + FrogConstant.SMS_JOIN_MEET);
            smsService.createSms(o);
            return R.ok();
        }
        return R.error("验证码发送失败!");
    }

    @Override
    @Transactional
    public void register(User user) {
        this.baseMapper.insert(user);
        //本地注册成功，调用IM注册
        /************************* 注册赠送蛙豆 ***************************/
        HyProductionScaleEntity vipScale = vacuateService.getOne(new QueryWrapper<HyProductionScaleEntity>().eq(
                "param_key",FrogConstant.SysConfigKey.REGISTER_SEND));
        addBean(user.getUid(), vipScale.getScale());
        /************************* 注册赠送积分 ***************************/
        // int registerScore =
        // integralConfigService.getObjectByType(ScoreSourceType.register.getCode());
        // 1.获取注册任务应赠送积分
        List<TaskRewardEntity> list = rewardService.findHyTaskRewardByCode(FrogxTaskCode.TaskCode.REGISTER);
        if(list.size() >= 1){
            TaskRewardEntity reward = rewardService.getHyTaskReward(list);
            // 5.完成任务
            TaskUserInfoEntity hyTaskUserInfo = new TaskUserInfoEntity();
            hyTaskUserInfo.setUid(user.getUid());
            hyTaskUserInfo.setRemark("注册赠送手机号" + user.getPhone());
            hyTaskUserInfo.setTaskId(list.get(0).getTid());
            hyTaskUserInfo.setTaskCode(FrogxTaskCode.TaskCode.REGISTER);
            hyTaskUserInfo.setTaskType(FrogxTaskCode.TaskType.NOVICE);
            hyTaskUserInfo.setStatus(FrogxTaskCode.TaskStatus.FINISH);
            hyTaskUserInfo.setRewardId(reward.getId());
            hyTaskUserInfo.setRewordScore(reward.getScore());
            userInfoService.UserInfoSave(hyTaskUserInfo);
        }

        /*************************
         * 注册补全邀请码预约记录表(如果存在预约记录表中,修改成激活用户，补全uid,uname,注册时间)
         ***************************/
        // 因为邀请者奖励在接受者填写邀请码时已给与,所以受邀请者在注册时也要完成该任务,并获取奖励发送积分
        HyInviteInfo inviteInfo = inviteInfoService.getHyInviteInfoByPhone(user.getPhone());
        if(inviteInfo != null){
            inviteInfo.setTuid(user.getUid());
            User tUser = this.baseMapper.selectByUid(Convert.toInt(user.getUid()));
            inviteInfo.setTuname(tUser.getUsername());
            inviteInfo.setRegisertime(tUser.getCreated());
            inviteInfo.setIsactive(1);
            inviteInfoService.updateById(inviteInfo);
        }
    }

    @Override
    public Page selectPageByConditions(QueryExt query) {
        Map map = new HashMap();
        map.putAll(query.getCondition());
        List<User> result = this.baseMapper.selectPageByConditions(query, map);
       /* if(result.size()>0){
            HyUserZoomOrder order = new HyUserZoomOrder();
            //HyUserZoom
            for(User user:result){
                order.setUid(user.getUid());
                order.setStatus(1);
                //专属会议室数=我买的+我是子账号的
                Map<String, Object> params = new HashMap<>();
                // 获取是否有专属会议室
                params.put("ouid", user.getUid());
                // 要关联查询专属名称、参会标记、所属账号【手机号】、附加账号数量、创建时间，启用时间、到期时间、
                Page page = meetingService.selectZoomMeeting(new QueryExt<>(params));
                user.setZoomNum(page.getRecords().size());
                //订单数
                user.setOrderNum(zoomOrderService.selectOrderCount(order));
            }
        }*/
        query.setRecords(result);
        return query;
    }

    /**
     * 手机号密码登录
     * @param form app用户表单
     * @return
     */
    @Override
    public User login(ClientUserForm form){
        User user = this.getOne(new QueryWrapper<User>().eq("phone",form.getPhone()));
        if(user == null){
            throw new MyException("手机号或密码错误");
        }
        if(!user.getPassword().equals(MD5Utils.MD5Encode(form.getPassword() + user.getPhone().substring(0,5)))){
            throw new MyException("手机号或密码错误");
        }
        if(user.getStatus() == 0){
            throw  new MyException("账号已被锁定,请联系管理员");
        }
        // 修改最后登录时间
        user.setUpdateTime(new Date());
        this.baseMapper.updateById(user);
        return  user;
    }


    @Override
    public String updateUserImg(MultipartFile file){

        String path = FrogConstant.Path.USER;
        if (StrUtil.isEmpty(path)) {
            throw new ServiceException("配置文件路径错误!");
        }
        if (!new File(path).exists()) {
            new File(path).mkdirs();
        }
        String fileName = UUID.randomUUID().toString() + file.getOriginalFilename()
                .substring(file.getOriginalFilename().lastIndexOf("."), file.getOriginalFilename().length());

        OutputStream os=null;
        InputStream is=null;
        // 获取输出流
        try {
            os = new FileOutputStream(path + fileName);
            // 获取输入流 CommonsMultipartFile 中可以直接得到文件的流
            is = file.getInputStream();
            int temp;
            while ((temp = is.read()) != (-1)) {
                os.write(temp);
            }
            os.flush();
            os.close();
            is.close();

            // 图片指定比例缩放与压缩
            float outputQuality = 0.95f;
            float scale = 1;
            Thumbnailator.scaleAndSize(path + fileName, path + fileName, scale, outputQuality);
            return fileName;
        }catch (Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public void addBean(Long uid, int bean) throws MyException {
        if (bean < 0) {
            throw new MyException("充值金额错误");
        }
        HyUserBean userBean = hyUserBeanService.getOne(new QueryWrapper<HyUserBean>().eq("uid",uid));
        if (userBean == null) {
            HyUserBean nuserBean = new HyUserBean();
            nuserBean.setUid(uid);
            nuserBean.setMoney(bean);
            hyUserBeanService.save(nuserBean);
        } else {
            userBean.setMoney(userBean.getMoney() + bean);
            hyUserBeanService.updateById(userBean);
        }

    }

    @Override
    public void reduce(Long uid, int bean) throws MyException {
        if (bean < 0) {
            throw new ServiceException("扣款金额错误");
        }
        HyUserBean userBean = hyUserBeanService.getOne(new QueryWrapper<HyUserBean>().eq("uid",uid));
        if (userBean == null) {
            throw new MyException("用户无余额或余额为0");
        } else {
            if(userBean.getMoney() - bean < 0){
                throw new MyException("余额不足以支付");
            }
            userBean.setMoney(userBean.getMoney() - bean);
            hyUserBeanService.updateById(userBean);
        }
    }

    @Override
    public int getMoneyByUid(Long uid) {
        HyUserBean userBean = hyUserBeanService.getOne(new QueryWrapper<HyUserBean>().eq("uid",uid));
        if (userBean == null) {
            return  0;
        }else{
            return  userBean.getMoney();
        }
    }

  @Override
  public Integer getIsFollowNull(Integer uid) {
    return getBaseMapper().getIsFollowNull(uid);
  }

  @Override
    public User getUserByPhone(String phone){
        User user = this.getOne(new QueryWrapper<User>().eq("phone",phone));
        return user;
    }
    @Override
    public void addScore(Long uid, int score){
        // TODO Auto-generated method stub
        if (score < 0) {
            throw new MyException("增加积分错误");
        }
        synchronized (scoreManager) {
            // 找不到余额
           /* Integer remain = scoreManager.get(FrogConstant.RedisKey.SCORE,uid);
            if (remain == null) {
                remain = 0;
            }
            scoreManager.put(FrogConstant.RedisKey.SCORE, uid, remain + score);*/
            // 如果数据库没有该用户积分，插入积分到数据库,否则更新数据库
            HyScore hyScore = hyScoreService.getOne(new QueryWrapper<HyScore>().eq("uid",uid));
            Integer remain = 0;
           if(ObjectUtil.isNull(hyScore))
           {
               hyScore = new HyScore();
               hyScore.setUid(uid);
               remain = remain+score;
               hyScore.setScore(remain);
               hyScoreService.save(hyScore);
           }
           else {
               remain = hyScore.getScore()+score;
               hyScore.setScore(remain);
               hyScoreService.updateById(hyScore);
           }
            // System.out.println("充值后余额---" +
            // scoreManager.get(FrogConstant.RedisKey.SCORE, uid));
        }
    }

    @Override
    public User getUsersById(Integer uid) throws ServiceException {
        User user = this.baseMapper.selectByUid(uid);
        // todo vip系统上线后做
        //user.setVip(userVipService.getUserVipByUid(user.getUid()));
        return user;
    }

  @Override
  public User getUserSelfInfoByUid(Integer uid) {
    return this.baseMapper.getUserSelfInfoByUid(uid);
  }

}
